package org.offsync.async

import java.net.SocketAddress
import java.net.SocketOption
import java.nio.channels.AsynchronousChannelGroup
import java.nio.channels.AsynchronousServerSocketChannel
import java.nio.channels.AsynchronousSocketChannel
import java.nio.channels.CompletionHandler
import java.nio.channels.spi.AsynchronousChannelProvider

class AsyncServerSocket(underlying: AsynchronousServerSocketChannel) {
  def accept[A](attachment: A)(f: (() => AsynchronousSocketChannel, A) => Unit): Unit = {
    underlying.accept(attachment, new CompletionHandler[AsynchronousSocketChannel, A] {
      def completed(result: AsynchronousSocketChannel, attachment: A): Unit = f({() => result}, attachment)
      def failed(t: Throwable, attachment: A): Unit = f({() => throw t}, attachment)
    })
  }

  def accept(f: (() => AsynchronousSocketChannel) => Unit): Unit = {
    underlying.accept(null, new CompletionHandler[AsynchronousSocketChannel, Null] {
      def completed(result: AsynchronousSocketChannel, attachment: Null): Unit = f {() => result}
      def failed(t: Throwable, attachment: Null): Unit = f {() => throw t}
    })
  }

  def bind(address: SocketAddress) = underlying.bind(address)

  def bind(address: SocketAddress, backlog: Integer) = underlying.bind(address, backlog)

  def provider(): AsynchronousChannelProvider = underlying.provider()
  
  def setOption[T](name: SocketOption[T], value: T) = underlying.setOption(name, value)
}

object AsyncServerSocket {
  def open() = AsynchronousServerSocketChannel.open()

  def open(group: AsynchronousChannelGroup) = AsynchronousServerSocketChannel.open(group)
}
